home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / midas060 / src / gusdac.asm < prev    next >
Encoding:
Assembly Source File  |  1997-01-16  |  13.9 KB  |  818 lines

  1. ;*    GUSDAC.ASM
  2. ;*
  3. ;* Gravis UltraSound Mixing Sound Device
  4. ;*
  5. ;* $Id: gusdac.asm,v 1.3 1997/01/16 18:41:59 pekangas Exp $
  6. ;*
  7. ;* Copyright 1996,1997 Housemarque Inc.
  8. ;*
  9. ;* This file is part of the MIDAS Sound System, and may only be
  10. ;* used, modified and distributed under the terms of the MIDAS
  11. ;* Sound System license, LICENSE.TXT. By continuing to use,
  12. ;* modify or distribute this file you indicate that you have
  13. ;* read the license and understand and accept it fully.
  14. ;*
  15.  
  16.  
  17.  
  18. IDEAL
  19. P386
  20. JUMPS
  21.  
  22. INCLUDE "lang.inc"
  23. INCLUDE "errors.inc"
  24. INCLUDE "sdevice.inc"
  25. INCLUDE "mixsd.inc"
  26. INCLUDE "dsm.inc"
  27. INCLUDE "dma.inc"
  28. INCLUDE "mutils.inc"
  29.  
  30. ;BORDERS = 1
  31.  
  32. GLOBAL    LANG dmaBufferSize : _int
  33. GLOBAL    LANG dmaPos : _int
  34. GLOBAL    LANG mixPos : _int
  35. GLOBAL    LANG buffer : dmaBuffer
  36. GLOBAL    LANG buffer2 : dmaBuffer
  37. GLOBAL    LANG uploaded : _int
  38.  
  39.  
  40. ;/***************************************************************************\
  41. ;*     enum gdcFunctIDs
  42. ;*     ----------------
  43. ;* Description:  ID numbers for GUS DAC Sound Device functions
  44. ;\***************************************************************************/
  45.  
  46. enum    gdcFunctIDs \
  47.     ID_gdcDetect = ID_gdc, \
  48.     ID_gdcInit, \
  49.     ID_gdcClose, \
  50.     ID_gdcStartPlay
  51.  
  52.  
  53.  
  54. DATASEG
  55.  
  56. IFDEF __PASCAL__
  57. EXTRN    GDC : SoundDevice
  58. ENDIF
  59.  
  60.  
  61. D_int        selreg
  62. D_int        voicesel
  63. D_int        datalow
  64. D_int        gdcRate
  65. D_int        gdcMode
  66. D_int        numChans
  67. D_int        bufHalf
  68. D_int        oldPos
  69. D_int        uploaded
  70. D_int        playing
  71. D_int           dmaActive
  72. D_int           gusDMAPos
  73.  
  74.  
  75. IDATASEG
  76.  
  77.  
  78. GDCCONFIGBITS = sdUsePort or sdUseDMA or sdUseMixRate or \
  79.         sdUseOutputMode or sdUseDSM
  80. GDCMODEBITS = sdMono or sd8bit or sd16bit
  81.  
  82. ; If compiling for Pascal, Sound Device name is gdcSD, from which the data
  83. ; will be copied to Sound Device GDC, defined in Pascal.
  84.  
  85. IFDEF    __PASCAL__
  86. SDNAM        equ    gdcSD
  87. ELSE
  88. SDNAM        equ    GDC
  89. ENDIF
  90.  
  91. GLOBAL    SDNAM : SoundDevice
  92.  
  93. SDNAM    SoundDevice    < \
  94.  0,\
  95.  GDCCONFIGBITS,\
  96.  220h, 0, 1,\
  97.  1, 1,\
  98.  GDCMODEBITS,\
  99.  ptr_to gdcSDName,\
  100.  ptr_to gdcCardNames,\
  101.  6, ptr_to gdcPortAddresses,\
  102.  ptr_to gdcDetect,\
  103.  ptr_to gdcInit,\
  104.  ptr_to gdcClose,\
  105.  ptr_to dsmGetMixRate,\
  106.  ptr_to mixsdGetMode,\
  107.  ptr_to mixsdOpenChannels,\
  108.  ptr_to dsmCloseChannels,\
  109.  ptr_to dsmClearChannels,\
  110.  ptr_to dsmMute,\
  111.  ptr_to dsmPause,\
  112.  ptr_to dsmSetMasterVolume,\
  113.  ptr_to dsmGetMasterVolume,\
  114.  ptr_to mixsdSetAmplification,\
  115.  ptr_to mixsdGetAmplification,\
  116.  ptr_to dsmPlaySound,\
  117.  ptr_to dsmReleaseSound\
  118.  ptr_to dsmStopSound,\
  119.  ptr_to dsmSetRate,\
  120.  ptr_to dsmGetRate,\
  121.  ptr_to dsmSetVolume,\
  122.  ptr_to dsmGetVolume,\
  123.  ptr_to dsmSetSample,\
  124.  ptr_to dsmGetSample,\
  125.  ptr_to dsmSetPosition,\
  126.  ptr_to dsmGetPosition,\
  127.  ptr_to dsmGetDirection,\
  128.  ptr_to dsmSetPanning,\
  129.  ptr_to dsmGetPanning,\
  130.  ptr_to dsmMuteChannel,\
  131.  ptr_to dsmAddSample,\
  132.  ptr_to dsmRemoveSample,\
  133.  ptr_to mixsdSetUpdRate,\
  134.  ptr_to gdcStartPlay,\
  135.  ptr_to gdcPlay >
  136.  
  137. gdcSDName    DB    "Gravis UltraSound Mixing Sound Device v0.05", 0
  138.  
  139. gdcCardNames    DD    ptr_to gdcName
  140.  
  141. gdcName     DB    "Gravis UltraSound Software Mixing", 0
  142.  
  143. IFDEF __16__
  144. gdcPortAddresses  DW    210h, 220h, 230h, 240h, 250h, 260h
  145. ELSE
  146. gdcPortAddresses  DD    210h, 220h, 230h, 240h, 250h, 260h
  147. ENDIF
  148.  
  149. env        DB    "ULTRASND",0
  150.  
  151. chantab dw    44100,41160,38587,36317,34300,32494,30870,29400,28063,26843
  152.     dw    25725,24696,23746,22866,22050,21289,20580,19916,19293
  153.  
  154. buffer2 dmaBuffer ?
  155.  
  156.  
  157. CODESEG
  158.  
  159. MACRO    SetBorder    color
  160. IFDEF BORDERS
  161.     push    _dx _ax
  162.     mov    dx,03DAh
  163.     in    al,dx
  164.     mov    dx,03C0h
  165.     mov    al,31h
  166.     out    dx,al
  167.     mov    al,color
  168.     out    dx,al
  169.     pop    _ax _dx
  170. ENDIF
  171. ENDM
  172.  
  173. ;******* GUS Register Select - Macro ************
  174.  
  175. MACRO    regsel    register
  176.     mov    _dx,[selreg]
  177.     mov    al,register
  178.     out    dx,al
  179. ENDM
  180.  
  181. ;******* GUS-delay subroutine ************
  182.  
  183. PROC    gusdelay NEAR
  184.     push    _dx _ax
  185.     mov    dx,84h
  186.     rept    8
  187.     in    al,dx
  188.     endm
  189.     pop    _ax _dx
  190.     ret
  191. ENDP
  192.  
  193. ;/***************************************************************************\
  194. ;*
  195. ;* Function:    gusReset
  196. ;*
  197. ;* Description: Resets the GUS card
  198. ;*
  199. ;* Destroys:    al, dx
  200. ;*
  201. ;\***************************************************************************/
  202. PROC    gusReset NEAR
  203.  
  204.     regsel    4ch                ; RESET
  205.     add    _dx,2
  206.     xor    al,al
  207.     out    dx,al                ; RESET!
  208.  
  209.     call    gusdelay
  210.     call    gusdelay
  211.  
  212.     mov    al,1
  213.     out    dx,al                ; Enable GF1
  214.  
  215.     call    gusdelay
  216.     call    gusdelay
  217.     ret
  218. ENDP
  219.  
  220.  
  221. ;/***************************************************************************\
  222. ;*
  223. ;* Function:    int gdcDetect(int *result);
  224. ;*
  225. ;* Description: Detects Gravis UltraSound soundcard
  226. ;*
  227. ;* Returns:    MIDAS error code.
  228. ;*        1 stored to *result if GUS was detected, 0 if not.
  229. ;*
  230. ;\***************************************************************************/
  231.  
  232. PROC    gdcDetect    _funct    result : _ptr
  233. USES    _bx
  234.  
  235.     ; Search for "ULTRASND" environment string:
  236. IFDEF __16__
  237.     call    mGetEnv LANG, seg env offset env
  238.     mov    bx,dx            ; was "ULTRASND" environment found?
  239.     or    bx,ax            ; if not, no GUS
  240.     jz    @@noGUS
  241.  
  242.     mov    es,dx            ; point es:si to environment
  243.     mov    bx,ax            ; string
  244.  
  245. ELSE
  246.     call    mGetEnv LANG, offset env
  247.     test    eax,eax         ; was "ULTRASND" environment found?
  248.     jz    @@noGUS         ; if not, no GUS
  249.  
  250.     mov    ebx,eax         ; point _esbx to environment string
  251.  
  252. ENDIF
  253.     mov    cl,3                ; 3 digits
  254.     xor    _ax,_ax
  255. @@dloop:
  256.     mov    dl,[_esbx]
  257.     inc    _bx
  258.     sub    dl,"0"
  259.     shl    _ax,4
  260.     add    al,dl
  261.     dec    cl
  262.     jnz    @@dloop
  263.  
  264.     mov    [GDC.port],_ax
  265.  
  266. ; Take Playback DMA-channel
  267.     inc    _bx
  268.     xor    _dx,_dx
  269.     mov    dl,[_esbx]
  270.     sub    dl,"0"
  271.     mov    [GDC.DMA],_dx
  272.  
  273. ; Test if there really is a GUS
  274.  
  275.     add    _ax,103h
  276.     mov    [selreg],_ax            ; Register select (2x0h+103h)
  277.  
  278.     call    gusReset
  279.  
  280.     regsel    44h
  281.     add    _dx,2
  282.     xor    al,al
  283.     out    dx,al                ; upper bits of address
  284.  
  285.     regsel    43h
  286.     inc    _dx
  287.     xor    _ax,_ax             ; Address 0
  288.     out    dx,ax
  289.     add    dx,3
  290.     mov    al,055h
  291.     out    dx,al                ; Poke data 1 (55h)
  292.  
  293.     sub    dx,3
  294.     mov    _ax,1                ; Address 1
  295.     out    dx,ax
  296.     add    dx,3
  297.     mov    al,0AAh
  298.     out    dx,al                ; Poke data 2 (AAh)
  299.  
  300.     sub    dx,3
  301.     xor    _ax,_ax             ; Address 0
  302.     out    dx,ax
  303.     add    dx,3
  304.     in    al,dx                ; Peek data 1
  305.     cmp    al,055h
  306.     jne    @@noGUS
  307.  
  308.     sub    dx,3
  309.     mov    _ax,1                ; Address 1
  310.     out    dx,ax
  311.     add    dx,3
  312.     in    al,dx                ; Peek data 2
  313.     cmp    al,0AAh
  314.     je    @@found
  315.  
  316. @@noGUS:
  317.     mov    [GDC.port],0
  318.     xor    _ax,_ax             ; No GUS found
  319.     jmp    @@quit
  320.  
  321. @@found:
  322.     mov    _ax,1                ; GUS found
  323. @@quit:
  324.     LOADPTR es,_bx,[result]         ; store in *result
  325.     mov    [_int _esbx],_ax
  326.     xor    _ax,_ax
  327.     ret
  328. ENDP
  329.  
  330.  
  331. ;/***************************************************************************\
  332. ;*
  333. ;* Function:    int gdcInit(unsigned mixRate, unsigned mode);
  334. ;*
  335. ;* Description: Initializes Gravis UltraSound
  336. ;*
  337. ;* Input:    unsigned mixRate    mixing rate
  338. ;*        unsigned mode        output mode (see enum sdMode)
  339. ;*
  340. ;* Returns:    MIDAS error code
  341. ;*
  342. ;\***************************************************************************/
  343.  
  344. PROC    gdcInit     _funct    mixRate : _int, mode : _int
  345. USES    _si,_di,_bx
  346.  
  347.     mov    [gdcMode],0
  348.  
  349.     test    [mode],sd8bit        ; force 8-bit?
  350.     jnz    @@8b
  351.     or    [gdcMode],sd16bit    ; if not, use 16 bits
  352.     jmp    @@bit
  353. @@8b:    or    [gdcMode],sd8bit
  354.  
  355. @@bit:
  356. ; FIXME!!!
  357.     or    [gdcMode],sdMono
  358.     mov    _ax,[mixRate]
  359.  
  360.     mov    [gdcRate],_ax
  361.     mov    [numChans],14            ; Always 14 channels active
  362.                         ; in mono mode
  363.     mov    [bufHalf],0
  364.     mov    [oldPos],0
  365.     mov    [playing],0
  366.  
  367.     mov    _ax,[GDC.port]            ; Base address (Set before!)
  368.     add    _ax,103h
  369.     mov    [selreg],_ax            ; Register select (2x0h+103h)
  370.     dec    _ax
  371.     mov    [voicesel],_ax            ; Voice select (2x0h+102h)
  372.     add    _ax,2
  373.     mov    [datalow],_ax            ; Data Low Byte (2x0h+104h)
  374.  
  375.     call    gusReset            ; Reset GUS
  376.  
  377.  
  378. ; Clear all 32 channels
  379.  
  380.     mov    _dx,[GDC.port]            ; Mixer
  381.     mov    al,3
  382.     out    dx,al                ; Disable Line in & out
  383.  
  384.     regsel    0eh
  385.     add    _dx,2
  386.     mov    al,31 OR 0c0h
  387.     out    dx,al                ; Set number of active
  388.                         ; voices to 32 just for
  389.                         ; sure
  390.  
  391.     mov    _cx,32                ; Number of voices
  392. @@resetloop:
  393.     mov    _dx,[voicesel]            ; Voice Select
  394.     mov    _ax,_cx
  395.     out    dx,al
  396.  
  397.     regsel    0                ; Voice control
  398.     add    _dx,2                ; data low
  399.     mov    al,3                ; Stop voice
  400.     out    dx,al
  401.  
  402.     regsel    9                ; Current Volume
  403.     inc    _dx                ; data high
  404.     mov    _ax,0500h            ; Zero volume
  405.     out    dx,ax
  406.  
  407.     regsel    12                ; Pan Position
  408.     add    _dx,2                ; data low
  409.     mov    al,8                ; Center
  410.     out    dx,al
  411.  
  412.     regsel    13                ; Volume Ramping
  413.     add    _dx,2                ; data low
  414.     mov    al,3                ; disable
  415.     out    dx,al
  416.  
  417.     regsel    6                ; Ramp Rate
  418.     add    _dx,2
  419.     mov    al,3fh                ; Rate
  420.     out    dx,al
  421.  
  422.     dec    _cx
  423.     jnz    @@resetloop
  424.  
  425.     ; Take care of common initialization for all mixing Sound Devices:
  426.     call    mixsdInit LANG, [gdcRate], [gdcMode], -1
  427.     test    _ax,_ax
  428.     jnz    @@err
  429.  
  430.  
  431.     ; Clear the GUS buffer
  432.  
  433.     regsel    4ch                ; RESET
  434.     add    _dx,2
  435.     mov    al,3
  436.     out    dx,al                ; Enable GF1 and DACs
  437.  
  438.     mov    _cx,[dmaBufferSize]
  439.     add    _cx,32
  440.  
  441.     xor    _bx,_bx
  442.  
  443.     regsel    44h                ; Addr hi
  444.     add    _dx,2                ; 3x5
  445.     xor    _ax,_ax
  446.     out    dx,al                ; upper bits of address
  447.  
  448.     regsel    43h                ; Addr lo
  449. @@cloop:
  450.     mov    _dx,[datalow]
  451.     mov    _ax,_bx
  452.     out    dx,ax
  453.     add    _dx,3                ; 3x7
  454.     xor    al,al
  455.     inc    _bx
  456.     out    dx,al
  457.     dec    _cx
  458.     jnz    @@cloop
  459.  
  460.  
  461.     ; Allocate an extra DMA buffer:
  462.     mov    _ax,[dmaBufferSize]
  463.     call    dmaAllocBuffer LANG, _ax, offset buffer2
  464.     test    _ax,_ax
  465.     jnz    @@err
  466.  
  467.     ; Set amount of open channels:
  468.  
  469.     regsel    0eh
  470.     add    _dx,2
  471.     mov    _ax,[numChans]
  472.     dec    _ax                ; Amount-1
  473.     or    al,0c0h
  474.     out    dx,al
  475.  
  476.     mov    _ax,[gdcRate]
  477.     shl    _ax,10
  478.     xor    _dx,_dx
  479.     mov    _bx,44100
  480.     div    _bx
  481.     and    _ax,NOT 1
  482.  
  483.     push    _ax
  484.  
  485.     mov    _dx,[voicesel]            ; Select voice
  486.     xor    _ax,_ax
  487.     out    dx,al
  488.  
  489.     regsel    1                ; Frequency control
  490.     inc    _dx
  491.     pop    _ax
  492.     out    dx,ax
  493.  
  494.     mov    _cx,[dmaBufferSize]        ; Set sample end
  495.     test    [gdcMode],sd16bit
  496.     jz    @@bit8
  497.     shr    _cx,1
  498. @@bit8:
  499.     dec    _cx
  500.     regsel    4                ; End position high
  501.     inc    _dx
  502.     mov    _ax,_cx
  503.     shr    _ax,7
  504.     out    dx,ax
  505.     regsel    5                ; End position low
  506.     inc    _dx
  507.     mov    _ax,_cx
  508.     shl    _ax,9
  509.     out    dx,ax
  510.  
  511.     regsel    2                ; Start position high
  512.     inc    _dx
  513.     xor    _ax,_ax
  514.     out    dx,ax
  515.     regsel    3                ; Start position low
  516.     inc    _dx
  517.     xor    _ax,_ax
  518.     out    dx,ax
  519.  
  520.     regsel    10                ; Current position high
  521.     inc    _dx
  522.     xor    _ax,_ax
  523.     out    dx,ax
  524.     regsel    11                ; Current position low
  525.     inc    _dx
  526.     xor    _ax,_ax
  527.     out    dx,ax
  528.  
  529.     call    gusdelay
  530.  
  531.     out    dx,ax
  532.  
  533.     regsel    10                ; Current position high
  534.     inc    _dx
  535.     xor    _ax,_ax
  536.     out    dx,ax
  537.  
  538.     regsel    0                ; Voice control
  539.     mov    al,8                ; Loop
  540.     test    [gdcMode],sd16bit
  541.     jz    @@8bit
  542.     or    al,4                ; 16 bit
  543. @@8bit: add    _dx,2
  544.     out    dx,al
  545.     call    gusdelay            ; Delay
  546.     out    dx,al
  547.  
  548.     regsel    9                ; Current volume
  549.     inc    _dx
  550.     mov    ax,0ef00h
  551.     out    dx,ax
  552.     call    gusdelay
  553.     out    dx,ax
  554.  
  555.     call    dmaStop LANG, [GDC.DMA]
  556.  
  557.     regsel    41h
  558.     add    _dx,2
  559.     xor    al,al
  560.     out    dx,al
  561.  
  562.     mov    _dx,[GDC.port]            ; Mixer
  563.     xor    al,al
  564.     out    dx,al                ; Enable Line in & out
  565.  
  566. @@ok:    xor    _ax,_ax             ; gdc succesfully initialized
  567.     jmp    @@done
  568.  
  569.  
  570. @@err:    ERROR    ID_gdcInit
  571.  
  572. @@done:
  573.     ret
  574. ENDP
  575.  
  576.  
  577.  
  578. ;/***************************************************************************\
  579. ;*
  580. ;* Function:    int gdcClose(void)
  581. ;*
  582. ;* Description: Uninitializes Gravis UltraSound
  583. ;*
  584. ;* Returns:    MIDAS error code
  585. ;*
  586. ;\***************************************************************************/
  587.  
  588. PROC    gdcClose    _funct
  589. USES    _bx
  590.  
  591.     ; Stop DMA
  592.     call    dmaStop LANG, [GDC.DMA]
  593.  
  594.     regsel    41h
  595.     add    _dx,2
  596.     xor    al,al
  597.     out    dx,al
  598.  
  599.     call    gusReset
  600.  
  601.     mov    _dx,[GDC.port]            ; Mixer
  602.     xor    al,al
  603.     out    dx,al                ; Enable Line in & out
  604.  
  605.     ; Free the extra DMA buffer
  606.     mov    _ax,[dmaBufferSize]
  607.     mov    [buffer2.bufferLen],_ax
  608.     call    dmaFreeBuffer LANG, offset buffer2
  609.     test    _ax,_ax
  610.     jnz    @@err
  611.  
  612.     ; Take care of common uninitialization for all mixing Sound Devices:
  613.     call    mixsdClose
  614.     test    _ax,_ax
  615.     jnz    @@err
  616.  
  617.     xor    _ax,_ax
  618.     jmp    @@done
  619.  
  620.  
  621. @@err:    ERROR    ID_gdcClose
  622.  
  623. @@done:
  624.     ret
  625. ENDP
  626.  
  627.  
  628. ;/***************************************************************************\
  629. ;*
  630. ;* Function:    int gdcStartPlay(void)
  631. ;*
  632. ;* Description: Update the "DMA"-position of GUS
  633. ;*
  634. ;* Returns:    MIDAS error code
  635. ;*
  636. ;\***************************************************************************/
  637.  
  638. PROC    gdcStartPlay    _funct
  639. USES    _bx
  640.  
  641.         mov     [dmaActive],0
  642.  
  643.     mov    _dx,[voicesel]            ; Select voice
  644.     xor    _ax,_ax
  645.     out    dx,al
  646.  
  647.     regsel    8ah                ; Current position high
  648.     inc    _dx
  649.     in    ax,dx
  650.  
  651.     xor    ecx,ecx
  652.     mov    _cx,_ax
  653.     and    _cx,01fffh
  654.     shl    ecx,7
  655.  
  656.     regsel    8bh                ; Current position low
  657.     inc    _dx
  658.     in    ax,dx
  659.     shr    _ax,9
  660.     or    _cx,_ax
  661.  
  662.     test    [gdcMode],sd16bit
  663.     jz    @@ok16
  664.     add    _cx,_cx
  665. @@ok16:
  666.     mov    _ax,_cx
  667.     xor    _dx,_dx
  668.     idiv    [dmaBufferSize]
  669.     mov    [dmaPos],_dx
  670.  
  671.     xor    _ax,_ax
  672.     ret
  673. ENDP
  674.  
  675. ;/***************************************************************************\
  676. ;*
  677. ;* Function:    int gdcPlay(int *play)
  678. ;*
  679. ;* Description: Uploads the mixing buffer contents to GUS
  680. ;*
  681. ;* Returns:    MIDAS error code
  682. ;*
  683. ;\***************************************************************************/
  684.  
  685. PROC    gdcPlay    _funct  play:dword
  686. USES    _si,_di,_bx
  687.  
  688.     call    mixsdPlay LANG, [play]
  689.  
  690.     SetBorder(15)
  691.  
  692.         cmp     [dmaActive],0
  693.         jne     @@skip
  694.  
  695.         cmp     [playing],0
  696.         je      @@nodmacheck
  697.  
  698.         call    dmaGetPos LANG, offset buffer2, offset gusDMAPos
  699.         mov     _si,[gusDMAPos]
  700.         mov     _di,8
  701.  
  702. @@waitchange:
  703.         call    dmaGetPos LANG, offset buffer2, offset gusDMAPos
  704.         cmp     _si,[gusDMAPos]
  705.         jne     @@skip
  706.         call    gusdelay
  707.         dec     _di
  708.         jnz     @@waitchange
  709.  
  710. ;        regsel  41h
  711. ;        add     _dx,2
  712. ;        in      al,dx
  713. ;        test    al,40h
  714. ;        jz      @@skip
  715.  
  716. @@nodmacheck:
  717.     mov    _cx,[mixPos]
  718.     and    _cx,NOT 31
  719.     sub    _cx,[oldPos]
  720.     jns    @@ok
  721.  
  722.     mov    _cx,[dmaBufferSize]
  723.     sub    _cx,[oldPos]
  724.     mov    _bx,[oldPos]
  725.     mov    [oldPos],0
  726.     test    _cx,_cx
  727.     jz    @@skip
  728.     jmp    @@copy
  729.  
  730. @@ok:    cmp    _cx,64
  731.     jbe    @@skip
  732.  
  733.     mov    _bx,[oldPos]
  734.     mov    _ax,[mixPos]
  735.     and    _ax,NOT 31
  736.     mov    [oldPos],_ax
  737.  
  738. @@copy:
  739.     mov    [buffer2.bufferLen],_cx
  740.     mov    [uploaded],_cx
  741.     PUSHSEGREG ds
  742.         LOADPTR ds,_si,[buffer.bufDataPtr]
  743.         LOADPTR es,_di,[buffer2.bufDataPtr]
  744.     add    _si,_bx
  745.     shr    _cx,2
  746.     cld
  747.     rep    movsd
  748.     POPSEGREG ds
  749.  
  750.     push    _bx
  751.     call    dmaStop LANG, [GDC.DMA]
  752.  
  753.     regsel    41h
  754.     add    _dx,2
  755.     xor    al,al
  756.     out    dx,al
  757.     call    gusdelay
  758.     out    dx,al
  759.     pop    _bx
  760.  
  761.     shr    _bx,4
  762.     cmp    [GDC.DMA],4
  763.     jb    @@nope
  764.     shr    _bx,1
  765. @@nope:
  766.     regsel    42h
  767.     inc    _dx
  768.     mov    _ax,_bx
  769.     out    dx,ax
  770.  
  771.     regsel    41h
  772.     add    _dx,2
  773.  
  774.     mov    al,00000001b            ; 650kb/s
  775. ;     mov     al,00001001b             ; 325kb/s
  776. ;     mov     al,00010001b             ; 217kb/s
  777. ;     mov     al,00011001b             ; 163kb/s
  778.         or      al,20h
  779.     cmp    [GDC.DMA],4
  780.     jb    @@dmaok2
  781.     or    al,4                ; 16-bit DMA channel
  782. @@dmaok2:
  783.     test    [gdcMode],sd8bit
  784.     jz    @@oka2
  785.     or    al,80h                ; Invert high bit
  786. @@oka2:
  787. ; And START!
  788.     out    dx,al
  789.     call    gusdelay
  790.     out    dx,al
  791.  
  792.     call    dmaPlayBuffer LANG, offset buffer2, [GDC.DMA], 0
  793.  
  794.     regsel    41h
  795.     add    _dx,2
  796.     in    al,dx
  797.  
  798.     mov    [playing],1
  799.         mov     [dmaActive],1
  800. @@skip:
  801.     SetBorder(0)
  802.     xor    _ax,_ax
  803.     ret
  804. ENDP
  805.  
  806.  
  807. ;* $Log: gusdac.asm,v $
  808. ;* Revision 1.3  1997/01/16 18:41:59  pekangas
  809. ;* Changed copyright messages to Housemarque
  810. ;*
  811. ;* Revision 1.2  1996/08/04 11:29:00  pekangas
  812. ;* All functions now preserve _Bx
  813. ;*
  814. ;* Revision 1.1  1996/05/22 20:49:33  pekangas
  815. ;* Initial revision
  816. ;*
  817.  
  818. END